#include "stdafx.h"

USING_NAMESPACE_PBBIM_CORE
USING_NAMESPACE_BENTLEY_SQLITE
USING_NAMESPACE_BENTLEY_SQLITE_EC
USING_NAMESPACE_EC
USING_NAMESPACE_PBBIM_CORE
USING_NAMESPACE_PBBIM_COREMODEL

// new element : Vars define
"%BentleyVarsDefine%"

// new element : Vars init
/*=================================================================================**//**
* @bsimethod                                     %Author%                        %CreateTime%
+===============+===============+===============+===============+===============+======*/
PB%Class%::PB%Class%() : 
"%BentleyVarsInit%"
     %BaseClassName%()
{
    //m_Profile = CurveVector::Create(CurveVector::BOUNDARY_TYPE_Outer);
}

/*=================================================================================**//**
* @bsimethod                                     %Author%                        %CreateTime%
+===============+===============+===============+===============+===============+======*/
PB%Class%::~PB%Class%()
{
}

/*
/*=================================================================================**//**
* @bsimethod                                     %Author%                        %CreateTime%
+===============+===============+===============+===============+===============+======*/
bool PB%Class%::AddProfileCurve(ICurvePrimitiveR val)
{
    if (m_Profile != NULL)
    {
        m_Profile->Add(&val);
        return true;
    }
    return false;
}

/*=================================================================================**//**
* @bsimethod                                     %Author%                        %CreateTime%
+===============+===============+===============+===============+===============+======*/
ICurvePrimitivePtr PB%Class%::GetProfileCurve(int i)
{
    if (m_Profile != NULL&&i < (int)m_Profile->size())
    {
        return m_Profile->at(i);
    }
    else
        return NULL;
}

/*=================================================================================**//**
* @bsimethod                                     %Author%                        %CreateTime%
+===============+===============+===============+===============+===============+======*/
void PB%Class%::ClearProfileCurve()
{
    if (m_Profile != NULL)
        m_Profile->clear();
}

/*=================================================================================**//**
* @bsimethod                                     %Author%                        %CreateTime%
+===============+===============+===============+===============+===============+======*/
int PB%Class%::GetProfileCurveCount()
{
    if (m_Profile != NULL)
        return (int)m_Profile->size();
    return 0;
}

*/

/*=================================================================================**//**
* @bsimethod                                     %Author%                        %CreateTime%
+===============+===============+===============+===============+===============+======*/
StatusInt PB%Class%::_SetInstanceValues(BentleyApi::ECN::IECInstanceR instance)
{
	// new element : SetInstanceValues
    if (T_Super::_SetInstanceValues(instance) != ECOBJECTS_STATUS_Success)
        return ERROR;
    ECObjectsStatus status;

	"%BentleyVarsSetInstance%"

    //if (m_Profile != NULL)
    //{
    //    int n = (int)m_Profile->size();
    //    DSegment3d* segments = new DSegment3d[n];
    //    for (int i = 0; i < n; i++)
    //    {
    //        ICurvePrimitivePtr curveP = this->GetProfileCurve(i);

    //        DPoint3d pointAP;
    //        DPoint3d pointBP;
    //        curveP->GetStartEnd(pointAP, pointBP);
    //        segments[i].Init(pointAP, pointBP);
    //    }
    //    ECValue valueProfile;
    //    BentleyStatus status2 = valueProfile.SetBinary((byte*)&segments[0], sizeof (DSegment3d)* n);
    //    if (status2 != BentleyStatus::SUCCESS)
    //        return ERROR;
    //    status = instance.SetValue(Property_Profile, valueProfile);
    //    if (ECOBJECTS_STATUS_Success != status)
    //        return ERROR;
    //}

    //status = instance.SetValue(Property_%Class%Type, ECValue(this->Get%Class%Type()));
    //if (ECOBJECTS_STATUS_Success != status)
    //    return ERROR;

    //status = instance.SetValue(Property_Thickness, ECValue(this->GetThickness()));
    //if (ECOBJECTS_STATUS_Success != status)
    //    return ERROR;

    return SUCCESS;
}

/*=================================================================================**//**
* @bsimethod                                     %Author%                        %CreateTime%
+===============+===============+===============+===============+===============+======*/
StatusInt PB%Class%::_GetInstanceValues(BentleyApi::ECN::IECInstanceCR instance)
{
	// new element : GetInstanceValues
    if (T_Super::_GetInstanceValues(instance) != ECOBJECTS_STATUS_Success)
        return ERROR;
    ECObjectsStatus status;
    ECValue ecValue;

	"%BentleyVarsGetInstance%"

 /*   status = instance.GetValue(ecValue, Property_Profile);
    if (ECOBJECTS_STATUS_Success != status)
        return ERROR;

    size_t binarySize = 0;
    const byte * datas = ecValue.GetBinary(binarySize);
    int length = sizeof(DSegment3d);
    if (NULL == datas && binarySize < length)
        return false;
    int n = ((int)binarySize) / length;
    for (int i = 0; i < n; i++)
    {
        byte* dataSeg = new byte[length];
        for (int j = 0; j < sizeof(DSegment3d); j++)
        {
            dataSeg[j] = datas[j + i*length];
        }
        DSegment3d segment = *(DSegment3d*)dataSeg;
        ICurvePrimitivePtr curvePtr = ICurvePrimitive::CreateLine(segment);
        this->AddProfileCurve(*curvePtr);
    }

    status = instance.GetValue(ecValue, Property_%Class%Type);
    if (ECOBJECTS_STATUS_Success != status)
        return ERROR;
    this->Set%Class%Type(ecValue.GetInteger());

    status = instance.GetValue(ecValue, Property_Thickness);
    if (ECOBJECTS_STATUS_Success != status)
        return ERROR;
    this->SetThickness(ecValue.GetDouble());*/

    return SUCCESS;
}

BEGIN_PBBIM_CORE_NAMESPACE

/*=================================================================================**//**
* @bsiclass                         %Author%                        %CreateTime%
+===============+===============+===============+===============+===============+======*/
class PB%Class%ItemHandler : public PhysicalItemHandler
{
protected:
/*---------------------------------------------------------------------------------**//**
* @bsimethod                                    %Author%                        %CreateTime%
+---------------+---------------+---------------+---------------+---------------+------*/
    virtual PhysicalGeometryPtr _GetPhysicalGeometry(TransformR localToWorld, ECDbR db, ECInstanceKeyCR instanceKey) override
    {
        ECInstanceId instId = instanceKey.GetECInstanceId();
        IECInstancePtr instance = ObjectUtil::GetInstance(db,instId, %schemaName%, %schemaClassDefine%);
        if (!instance.IsValid()) return nullptr;

        PB%Class% pb%Class%;
        pb%Class%.GetInstanceValues(*instance);
        localToWorld = pb%Class%.GetPlacement().ToTransform();

        return CreatePhysicalGeometry (pb%Class%);
    }

/*---------------------------------------------------------------------------------**//**
* @bsimethod                                    %Author%                        %CreateTime%
+---------------+---------------+---------------+---------------+---------------+------*/
    virtual PhysicalGeometryPtr _GetPhysicalGeometry(BentleyApi::ECN::IECInstanceCR instance) override
    {
        PB%Class% pb%Class%;
        pb%Class%.GetInstanceValues(instance);

        return CreatePhysicalGeometry (pb%Class%);
    }

/*---------------------------------------------------------------------------------**//**
* @bsimethod                                    %Author%                        %CreateTime%
+---------------+---------------+---------------+---------------+---------------+------*/
    virtual bool _CanHandleClass(BentleyApi::BeSQLite::EC::ECDbCR db, BentleyApi::ECN::ECClassId ecClassId) override
    {
        ECClassP ecClassP = NULL;
        if (BSISUCCESS != db.GetEC().GetSchemaManager().GetECClass(ecClassP, %schemaName%, %schemaClassDefine%))
            return false;

        return (ecClassP->GetId() == ecClassId);
    }

/*---------------------------------------------------------------------------------**//**
* @bsimethod                                    %Author%                        %CreateTime%
+---------------+---------------+---------------+---------------+---------------+------*/
    virtual BentleyApi::ECN::ECRelationshipClassCP _GetRelationshipToTag(BentleyApi::ECN::ECClassCR) override
    {
        return NULL;
    }

public:
/*---------------------------------------------------------------------------------**//**
* @bsimethod                                    %Author%                        %CreateTime%
+---------------+---------------+---------------+---------------+---------------+------*/
    static PhysicalGeometryPtr CreatePhysicalGeometry(PB%Class%CR %Class%Data)
    {
		// new element : element draw
        PhysicalGeometryPtr physicalGeometryPtr = nullptr;

        const double z=%Class%Data.GetThickness();
        DgnExtrusionDetail extrData(%Class%Data.GetProfile(), DVec3d::From(0, 0, z), true);
        ISolidPrimitivePtr extrusion = ISolidPrimitive::CreateDgnExtrusion(extrData);
        if (extrusion.IsNull())
            return nullptr;

        physicalGeometryPtr = PhysicalGeometry::Create();
        physicalGeometryPtr->AddPart(PlacedPhysicalGeometryPart(PartCategoryId::%Class%, PartMaterialId::Cardboard, IGeometryExt::Create(extrusion.get ()).get ()));

        return physicalGeometryPtr;
    }

};

END_PBBIM_CORE_NAMESPACE

static PB%Class%ItemHandler s_%ClassDown%ItemHandler;

/*=================================================================================**//**
* @bsiclass                         %Author%                        %CreateTime%
+===============+===============+===============+===============+===============+======*/
class PB%Class%Operator
{
private:
    PB%Class%R       m_%ClassDown%;

public:
/*---------------------------------------------------------------------------------**//**
* @bsimethod                                    %Author%                        %CreateTime%
+---------------+---------------+---------------+---------------+---------------+------*/
    PB%Class%Operator(PB%Class%R pb%Class%) : m_%ClassDown%(pb%Class%)
    {
    }

/*---------------------------------------------------------------------------------**//**
* @bsimethod                                    %Author%                        %CreateTime%
+---------------+---------------+---------------+---------------+---------------+------*/
    StatusInt AddToModel(ElementIdR newElementId, PBDesignContextCR designContext)
    {
        DgnModelP model = designContext.GetModel();
        if (NULL == model)
        {
            BeAssert(false && "NULL modelRef");
            return ERROR;
        }

        StandaloneECInstancePtr itemPtr = s_%ClassDown%ItemHandler.CreateItemInstance(model->GetDgnProject(), %schemaName%, %schemaClassDefine%);
        if (!itemPtr.IsValid())
            return ERROR;

        if (SUCCESS != m_%ClassDown%.SetInstanceValues(*itemPtr))
            return ERROR;

        ECInstanceKey itemKey = s_%ClassDown%ItemHandler.InsertItemInstance(model->GetDgnProject(), *itemPtr);
        if (!itemKey.IsValid())
            return ERROR;

        if (BSISUCCESS != DgnGraphicsUtils::InsertItemPhysicalGraphics(&newElementId, s_%ClassDown%ItemHandler, *model, itemKey, designContext.GetLevelId()))
            return ERROR;

        return SUCCESS;
    }
};

/*---------------------------------------------------------------------------------**//**
* @bsimethod                                    %Author%                        %CreateTime%
+---------------+---------------+---------------+---------------+---------------+------*/
StatusInt PB%Class%::_AddOrReplaceInModel(ElementIdR newElementId, PBDesignContextCR designContext)
{
    ElementIdCR elementId = GetElementId();
    bool add = !elementId.IsValid();

    if (!add)
    {
        BeAssert(false && "WIP");
        return ERROR;
    }

    PB%Class%Operator pb%Class%Operator(*this);

    return pb%Class%Operator.AddToModel(newElementId, designContext);
}

/*---------------------------------------------------------------------------------**//**
* @bsimethod                                    %Author%                        %CreateTime%
+---------------+---------------+---------------+---------------+---------------+------*/
StatusInt PB%Class%::_DeleteFromModel()
{
    return SUCCESS;
}

/*---------------------------------------------------------------------------------**//**
* @bsimethod                                    %Author%                        %CreateTime%
+---------------+---------------+---------------+---------------+---------------+------*/
StatusInt PB%Class%::_GetRelatedElements(T_ElementIdArrayR elements, bool recursive, RelatedDirection findRelatedDirections)
{
    return SUCCESS;
}

/*---------------------------------------------------------------------------------**//**
* @bsimethod                                    %Author%                        %CreateTime%
+---------------+---------------+---------------+---------------+---------------+------*/
PhysicalGraphicsPtr PB%Class%::_CreateDynamicGraphics(PBDesignContextCR designContext)
{
    PhysicalGeometryPtr physicalGeometryPtr = s_%ClassDown%ItemHandler.CreatePhysicalGeometry(*this);
    if (! physicalGeometryPtr.IsValid ())
        return NULL;

    YawPitchRollAngles placementAngles = this->GetPlacement().GetAngles();

    Transform localToWorld = placementAngles.ToTransform(this->GetPlacement().GetOrigin());

    return DgnGraphicsUtils::CreatePhysicalGraphicsFromPhysicalGeometry(*designContext.GetModel(), *physicalGeometryPtr, localToWorld, designContext.GetLevelId());
}
